home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 43 / Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso / -serious- / archivers / xpk / xpk_source / xpkmaster / password.c < prev    next >
C/C++ Source or Header  |  1999-06-14  |  13KB  |  469 lines

  1. #ifndef XPKMASTER_PASSWORD_C
  2. #define XPKMASTER_PASSWORD_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        password.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: password.c 1.13 (27.03.1998)
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    password requester related things
  12.  
  13.  1.0   27.12.96 : first version
  14.  1.1   28.12.96 : starting to code the stuff
  15.  1.2   29.12.96 : optimized and removed bugs
  16.  1.3   02.01.97 : corrected return handling
  17.  1.4   01.03.97 : fixed tag parsing error
  18.  1.5   10.04.97 : now old screen comes to front after Request
  19.  1.6   15.10.97 : TimeOut now uses timer.device
  20.  1.7   07.11.97 : timout of 0 again means no timeout
  21.  1.8   27.12.97 : added title line to passrequest
  22.  1.9   09.01.98 : gadget uses gadtools now
  23.  1.10  18.01.98 : added 5 position tags
  24.  1.11  21.01.98 : added verification mode
  25.  1.12  21.02.98 : uses new style register definition
  26.  1.13  27.03.98 : some optimizations
  27. */
  28.  
  29. #include <proto/intuition.h>
  30. #include <proto/exec.h>
  31. #include <proto/utility.h>
  32. #include <proto/gadtools.h>
  33. #include <exec/memory.h>
  34. #include <exec/errors.h>
  35. #include <intuition/sghooks.h>
  36. #include <intuition/intuitionbase.h>
  37. #include <intuition/gadgetclass.h>
  38. #include <xpk/xpk.h>
  39. #include <xpk/xpkprefs.h>
  40. #include "texts.h"
  41. #include "xpkmaster.h"
  42.  
  43. #define TESTSIZE    13
  44.  
  45. #define VERIFY_OFF    0
  46. #define VERIFY_ON    1
  47. #define VERIFY_ACTIVE    2
  48. #define VERIFY_DONE    3
  49.  
  50. static const struct PassCharData {
  51.   ULONG Flag;
  52.   UBYTE Lower;
  53.   UBYTE Upper;
  54. } TestField[TESTSIZE] = {
  55. {XPKPASSFF_30x39,0x30,0x39}, {XPKPASSFF_41x46,0x41,0x46},
  56. {XPKPASSFF_61x66,0x61,0x66}, {XPKPASSFF_47x5A,0x47,0x5A},
  57. {XPKPASSFF_67x7A,0x67,0x7A}, {XPKPASSFF_20,   0x20,0x20},
  58. {XPKPASSFF_SPECIAL7BIT,0x21,0x2F},
  59. {XPKPASSFF_SPECIAL7BIT,0x3A,0x40},
  60. {XPKPASSFF_SPECIAL7BIT,0x5B,0x60},
  61. {XPKPASSFF_SPECIAL7BIT,0x7B,0x7E},
  62. {XPKPASSFF_C0xDE,0xC0,0xDE}, {XPKPASSFF_DFxFF,0xDF,0xFF},
  63. {XPKPASSFF_SPECIAL8BIT,0xA0,0xBF},
  64. };
  65.  
  66. /* this is no public structure !! */
  67. struct RequestData {
  68.   ULONG            rd_Time;
  69.   ULONG            rd_GadgFlags;
  70.   ULONG            rd_BufSize;
  71.   WORD            rd_WinLeft;
  72.   WORD            rd_WinTop;
  73.   WORD            rd_WinWidth;
  74.   WORD            rd_WinHeight;
  75.   UWORD            rd_WinCenter;
  76.   UWORD            rd_Verify;
  77.   STRPTR        rd_Title;
  78.   STRPTR        rd_GivenBuffer;
  79.   struct Window *    rd_Window;
  80.   struct Screen *    rd_GivenScreen;
  81.   struct Screen *    rd_FirstScreen;
  82.   struct timerequest *  rd_TimeRequest;
  83.   STRPTR        rd_PassBuffer;
  84.   UBYTE            rd_ScreenTitle[80];
  85.   UBYTE            rd_KeyBuffer[9];
  86. };
  87.  
  88. static void SendTimerReq(struct RequestData *rd)
  89. {
  90.   rd->rd_TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
  91.   rd->rd_TimeRequest->tr_time.tv_secs = rd->rd_Time;
  92.   SendIO((struct IORequest *) rd->rd_TimeRequest);
  93. }
  94.  
  95. static ASM(ULONG) PassHookFunc(REG(a0, struct Hook *hook),
  96.     REG(a2, struct SGWork *sgw), REG(a1, ULONG *msg))
  97. {
  98.   struct RequestData *rd;
  99.  
  100.   rd = (struct RequestData *) sgw->Gadget->UserData;
  101.  
  102.   if(rd->rd_Time)
  103.     AbortIO((struct IORequest *) rd->rd_TimeRequest);
  104.  
  105.   if(*msg == SGH_KEY)
  106.   {
  107.     STRPTR passbuf = rd->rd_PassBuffer;
  108.     ULONG bufpos = sgw->BufferPos-1;
  109.     STRPTR wbuf = sgw->WorkBuffer;
  110.  
  111.     switch(sgw->EditOp)
  112.     {
  113.     case EO_INSERTCHAR:
  114.     {
  115.       register UBYTE c = sgw->Code;
  116.  
  117.       if(rd->rd_Verify == VERIFY_ACTIVE)
  118.       {
  119.         if(c != passbuf[bufpos])
  120.         {
  121.           sgw->Actions |= SGA_BEEP; /* let the screen beep */
  122.           sgw->Actions &= ~SGA_USE; /* do not use char */
  123.         }
  124.         else
  125.       wbuf[bufpos] = '*';
  126.       }
  127.       else
  128.       {
  129.         register ULONG i;
  130.         for(i = 0; i < TESTSIZE; ++i)
  131.         {
  132.           if((rd->rd_GadgFlags & TestField[i].Flag) &&
  133.           (c >= TestField[i].Lower) && (c <= TestField[i].Upper))
  134.             break;
  135.         }
  136.         if(i == TESTSIZE)
  137.         {
  138.           sgw->Actions |= SGA_BEEP; /* let the screen beep */
  139.           sgw->Actions &= ~SGA_USE; /* do not use char */
  140.         }
  141.         else
  142.         {
  143.           passbuf[bufpos] = c;
  144.           passbuf[sgw->NumChars] = 0;
  145.       wbuf[bufpos] = '*';
  146.         }
  147.       }
  148.     }
  149.     break;
  150.     case EO_CLEAR:
  151.       if(rd->rd_Verify != VERIFY_ACTIVE)
  152.         *passbuf = 0;
  153.       *wbuf = 0;
  154.       sgw->NumChars = sgw->BufferPos = 0;
  155.       sgw->EditOp = EO_BIGCHANGE;
  156.       break;
  157.     case EO_DELBACKWARD:
  158.       if(rd->rd_Verify != VERIFY_ACTIVE)
  159.         passbuf[sgw->NumChars] = 0;
  160.       break;
  161.     case EO_ENTER:
  162.       if(rd->rd_Verify == VERIFY_ON && sgw->NumChars)
  163.       {
  164.     SetWindowTitles(rd->rd_Window, strings[TXT_VERIFY_PASS], (STRPTR) ~0);
  165.         rd->rd_Verify = VERIFY_ACTIVE;
  166.         *wbuf = 0;
  167.         sgw->NumChars = sgw->BufferPos = 0;
  168.         sgw->EditOp = EO_BIGCHANGE;
  169.         sgw->Actions &= ~SGA_END;
  170.       }
  171.       else if(rd->rd_Verify == VERIFY_ACTIVE && !passbuf[sgw->NumChars])
  172.         rd->rd_Verify = VERIFY_DONE;
  173.     case EO_NOOP:
  174.       break;
  175.     /* prevent to complicated edit operations, like cursor move */
  176.     default:
  177.       sgw->Actions &= ~SGA_USE;
  178.       sgw->Actions |= SGA_BEEP;
  179.       break;
  180.     } /* switch */
  181.     return ~0;
  182.   }
  183.   else if(*msg == SGH_CLICK) /* on click set last character */
  184.   {
  185.     sgw->BufferPos = sgw->NumChars;
  186.     sgw->EditOp = EO_BIGCHANGE;
  187.   }
  188.   else
  189.     return 0;
  190. }
  191.  
  192. static struct Hook PassHook = { {0}, (ULONG (*) ()) PassHookFunc, 0, 0};
  193.  
  194. /* returns XPKERR codes */
  195. static LONG DoRequest(struct RequestData *rd)
  196. {
  197.   struct Screen *scr;
  198.   struct MsgPort *MsgPort = 0;
  199.   LONG err = XPKERR_UNKNOWN;
  200.  
  201.   if(rd->rd_GivenScreen)
  202.     scr = rd->rd_GivenScreen;
  203.   else if(!(scr = LockPubScreen(0)))
  204.     return XPKERR_UNKNOWN;
  205.  
  206.   *rd->rd_PassBuffer = 0;
  207.  
  208.   if(!rd->rd_Time || (MsgPort = CreateMsgPort()))
  209.   {
  210.     ULONG tflag = rd->rd_Time ? 1 << MsgPort->mp_SigBit : 0;
  211.  
  212.     if(!tflag || (rd->rd_TimeRequest = (struct timerequest *)
  213.     CreateIORequest(MsgPort, sizeof(struct timerequest))))
  214.     {
  215.       if(!tflag || !OpenDevice("timer.device",UNIT_VBLANK,
  216.       (struct IORequest *) rd->rd_TimeRequest,0))
  217.       {
  218.     APTR vi;
  219.  
  220.         if((vi = GetVisualInfoA(scr, 0)))
  221.         {
  222.           struct Gadget *gadg, *gl = 0;
  223.       struct NewGadget ng;
  224.           ULONG i;
  225.  
  226.       i = 4 + scr->WBorLeft + scr->WBorRight;
  227.  
  228.       if(rd->rd_WinWidth < i + 50)
  229.         rd->rd_WinWidth = scr->Width >> 1;
  230.       if(rd->rd_WinWidth > scr->Width)
  231.         rd->rd_WinWidth = scr->Width;
  232.       ng.ng_Width = rd->rd_WinWidth - i;
  233.  
  234.       i = 4 + scr->WBorTop + scr->Font->ta_YSize + 1 + scr->WBorBottom;
  235.  
  236.       if(rd->rd_WinHeight < i + scr->Font->ta_YSize + 6)
  237.         rd->rd_WinHeight = i + scr->Font->ta_YSize + 6;
  238.       if(rd->rd_WinHeight > scr->Height)
  239.         rd->rd_WinHeight = scr->Height;
  240.       ng.ng_Height = rd->rd_WinHeight - i;
  241.  
  242.       ng.ng_TopEdge = scr->WBorTop + scr->Font->ta_YSize + 1 + 2;
  243.       ng.ng_LeftEdge = scr->WBorLeft + 2;
  244.       ng.ng_GadgetText = 0;
  245.       ng.ng_TextAttr = scr->Font;
  246. /*      ng.ng_GadgetID is not used --> not initialized */
  247.       ng.ng_Flags = 0;
  248.       ng.ng_VisualInfo = vi;
  249.       ng.ng_UserData = rd;
  250.  
  251.       if(rd->rd_WinLeft < 0)
  252.         rd->rd_WinLeft = (scr->Width - rd->rd_WinWidth) >> 1;
  253.       else if(rd->rd_WinCenter)
  254.         rd->rd_WinLeft -= (rd->rd_WinWidth >> 1);
  255.  
  256.       if(rd->rd_WinTop < 0)
  257.         rd->rd_WinTop = (scr->Height - rd->rd_WinHeight) >> 1;
  258.       else if(rd->rd_WinCenter)
  259.         rd->rd_WinTop -= (rd->rd_WinHeight >> 1);
  260.  
  261.       if(rd->rd_WinTop < 0)
  262.         rd->rd_WinTop = 0;
  263.       if(rd->rd_WinLeft < 0)
  264.         rd->rd_WinLeft = 0;
  265.  
  266.       if((gadg = CreateContext(&gl)) && (gadg = CreateGadget(
  267.       STRING_KIND, gadg, &ng,
  268.       GTST_EditHook, &PassHook,
  269.       STRINGA_Justification, GACT_STRINGCENTER,
  270.       GTST_MaxChars, rd->rd_BufSize-1,
  271.       TAG_DONE)))
  272.           {
  273.         struct Window *window;
  274.  
  275.             if((rd->rd_Window = window = OpenWindowTags(0,
  276.           WA_Left, rd->rd_WinLeft,
  277.           WA_Top, rd->rd_WinTop,
  278.           WA_Height, rd->rd_WinHeight,
  279.           WA_Width, rd->rd_WinWidth,
  280.           WA_Gadgets, gl,
  281.           WA_IDCMP, IDCMP_GADGETUP|IDCMP_ACTIVEWINDOW|IDCMP_CLOSEWINDOW,
  282.           WA_Flags, WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_ACTIVATE|
  283.             WFLG_RMBTRAP|WFLG_CLOSEGADGET,
  284.           WA_Title, rd->rd_Title,
  285.           WA_PubScreen, scr,
  286.           WA_AutoAdjust, TRUE,
  287.           WA_PubScreenFallBack, TRUE, TAG_DONE)))
  288.             {
  289.               struct IntuiMessage *msg;
  290.               BOOL stop = 0;
  291.  
  292.               rd->rd_FirstScreen = IntuitionBase->FirstScreen;
  293.               ScreenToFront(scr);
  294.           if(tflag)
  295.             SendTimerReq(rd);
  296.  
  297.               while(!stop)
  298.               {
  299.             if((i = Wait((1<<window->UserPort->mp_SigBit)|tflag)) & tflag)
  300.             { /* when tflag is zero, this is never reached */
  301.               if(rd->rd_TimeRequest->tr_node.io_Error == IOERR_ABORTED)
  302.                 SendTimerReq(rd); /* got aborted, resend */
  303.               else
  304.                 stop = 20;
  305.             }
  306.  
  307.             if(i & (1 << window->UserPort->mp_SigBit))
  308.             {
  309.               while(!stop && (msg = (struct IntuiMessage *)
  310.               GetMsg(window->UserPort)))
  311.               {
  312.                 if(msg->Class == IDCMP_ACTIVEWINDOW)
  313.                   ActivateGadget(gadg, window, 0);
  314.                 else if(msg->Class == IDCMP_CLOSEWINDOW)
  315.                   stop = 10;
  316.                 else /* if(msg->Class == IDCMP_GADGETUP) */
  317.                   stop = 1;
  318.                 ReplyMsg((struct Message *) msg);
  319.               }
  320.             }
  321.           }
  322.           if(stop >= 20)
  323.             err = XPKERR_REQTIMEOUT;
  324.           else if(rd->rd_Verify == VERIFY_ACTIVE)
  325.         err = XPKERR_WRONGPW;
  326.           else if(stop >= 10 || !*rd->rd_PassBuffer)
  327.             err = XPKERR_ABORTED;
  328.           else
  329.             err = XPKERR_OK;
  330.  
  331.           if(tflag)
  332.           {
  333.             AbortIO((struct IORequest *) rd->rd_TimeRequest);
  334.             WaitIO((struct IORequest *) rd->rd_TimeRequest);
  335.           }
  336.             }
  337.             CloseWindow(window);
  338.             if(rd->rd_FirstScreen != scr) /* possibly dangerous routine */
  339.             {
  340.               struct Screen *sc;
  341.               Forbid();
  342.               sc = IntuitionBase->FirstScreen;
  343.               while((sc = sc->NextScreen) && sc != rd->rd_FirstScreen)
  344.                 ;
  345.               if(sc)
  346.                 ScreenToFront(sc);
  347.               Permit();
  348.             }
  349.           }
  350.           if(gl)
  351.             FreeGadgets(gl);
  352.           FreeVisualInfo(vi);
  353.         }
  354.  
  355.     if(tflag)
  356.           CloseDevice((struct IORequest *) rd->rd_TimeRequest);
  357.       }
  358.       if(rd->rd_TimeRequest)
  359.         DeleteIORequest(rd->rd_TimeRequest);
  360.     }
  361.     if(MsgPort)
  362.       DeleteMsgPort(MsgPort);
  363.   }
  364.  
  365.   if(!rd->rd_GivenScreen)
  366.     UnlockPubScreen(0, scr);
  367.  
  368.   return err;
  369. }
  370.  
  371. ASM(LONG) LIBXpkPassRequest(REG(a0, struct TagItem *ti))
  372. {
  373.   register struct RequestData *rd;
  374.   LONG mode = 0, useprefs = 1;
  375.   struct TagItem *tags = ti;
  376.  
  377. #ifdef DEBUG
  378.   DebugTagList("XpkPassRequest", tags);
  379. #endif
  380.  
  381.   if(!(rd = (struct RequestData *) AllocMem(sizeof(struct RequestData),
  382.   MEMF_PUBLIC|MEMF_CLEAR)))
  383.     return XPKERR_NOMEM;
  384.  
  385.   /* set defaults */
  386.   rd->rd_Time = 120;
  387.   rd->rd_GadgFlags = XPKPASSFLG_PRINTABLE;
  388.   rd->rd_WinLeft = rd->rd_WinTop = -1;
  389.  
  390.   while((ti = NextTagItem(&tags)))
  391.   {
  392.     switch(ti->ti_Tag)
  393.     {
  394.     case XPK_PassChars: rd->rd_GadgFlags = ti->ti_Data; break;
  395.     case XPK_PasswordBuf:
  396.       rd->rd_GivenBuffer = (STRPTR) ti->ti_Data; mode += 10; break;
  397.     case XPK_PassBufSize: rd->rd_BufSize = ti->ti_Data; break;
  398.     case XPK_Key16BitPtr:
  399.       rd->rd_GivenBuffer = (STRPTR) ti->ti_Data; mode += 11; break;
  400.     case XPK_Key32BitPtr:
  401.       rd->rd_GivenBuffer = (STRPTR) ti->ti_Data; mode += 12; break;
  402.     case XPK_PubScreen: rd->rd_GivenScreen = (struct Screen *) ti->ti_Data; break;
  403.     case XPK_PassTitle: rd->rd_Title = ti->ti_Data ? (STRPTR) ti->ti_Data : ""; break;
  404.     case XPK_TimeOut: useprefs = 0; rd->rd_Time = ti->ti_Data; break;
  405.     case XPK_Preferences: if(!ti->ti_Data) useprefs = 0; break;
  406.     case XPK_PassWinLeft: rd->rd_WinLeft = ti->ti_Data; break;
  407.     case XPK_PassWinTop: rd->rd_WinTop = ti->ti_Data; break;
  408.     case XPK_PassWinWidth: rd->rd_WinWidth = ti->ti_Data; break;
  409.     case XPK_PassWinHeight: rd->rd_WinHeight = ti->ti_Data; break;
  410.     case XPK_PassCenter: rd->rd_WinCenter = ti->ti_Data; break;
  411.     case XPK_PassVerify:
  412.       rd->rd_Verify = (ti->ti_Data ? VERIFY_ON : VERIFY_OFF); break;
  413.     };
  414.   }
  415.  
  416.   if(!mode || (mode > 12) || (mode == 10 && !rd->rd_BufSize) ||
  417.   !rd->rd_GivenBuffer)
  418.   {
  419.     FreeMem(rd, sizeof(struct RequestData));
  420.     return XPKERR_BADPARAMS;
  421.   }
  422.  
  423.   if(useprefs) /* call the preferences */
  424.   {
  425.     struct XpkPrefsSemaphore *sem;
  426.  
  427.     if((sem = GetPrefsSem()))
  428.     {
  429.       if(sem->xps_MainPrefs)
  430.         rd->rd_Time = sem->xps_MainPrefs->xmp_Timeout;
  431.       ReleaseSemaphore((struct SignalSemaphore *) sem);
  432.     }
  433.   }
  434.  
  435.   if(!rd->rd_Title) /* create title text */
  436.   {
  437.     if(mode == 10)
  438.       rd->rd_Title = strings[TXT_REQ_PASSWORD];
  439.     else
  440.     {
  441.       rd->rd_Title = rd->rd_ScreenTitle;
  442.       sprintf(rd->rd_ScreenTitle, strings[TXT_REQ_KEY], (mode == 11 ? 16 : 32));
  443.     }
  444.   }
  445.  
  446.   if(mode > 10)
  447.   {
  448.     rd->rd_BufSize = (mode == 11 ? 5 : 9);
  449.     rd->rd_PassBuffer = rd->rd_KeyBuffer;
  450.     rd->rd_GadgFlags = XPKPASSFLG_HEXADECIMAL;
  451.   }
  452.   else
  453.     rd->rd_PassBuffer = rd->rd_GivenBuffer;
  454.   
  455.   if(!(useprefs = DoRequest(rd)))
  456.   {
  457.     if(mode == 11)
  458.       *((UWORD *) rd->rd_GivenBuffer) = strtoul(rd->rd_PassBuffer, 0, 16);
  459.     else if(mode == 12)
  460.       *((ULONG *) rd->rd_GivenBuffer) = strtoul(rd->rd_PassBuffer, 0, 16);
  461.   }
  462.  
  463.   FreeMem(rd, sizeof(struct RequestData));
  464.  
  465.   return useprefs;
  466. }
  467.  
  468. #endif    /* XPKMASTER_PASSWORD_C */
  469.